import { Injectable } from "@angular/core";
import { FormBuilder, FormGroup, FormArray, FormControl } from "@angular/forms";

import { BladeContainerInterface } from "./blade-container.interface";
import { Blade } from "./blade.model";
import { BladeService } from "../blade.service";
import { BladeData } from "./blade-data";
import { DialogService, DialogResult } from "../dialog.service";
import { Command, ToolbarService } from "../toolbar.service";

import { Observable } from "rxjs/Observable";
import { startWith } from "rxjs/Operator/startWith";


@Injectable()
export class BladeContainerBase<T> implements BladeContainerInterface {
    /**
     * 当前弹出层对象
     * 
     * @type {Blade}
     * @memberof BladeContainerBase
     */
    currentBlade: Blade;
    /**
     * 命令集合
     * 
     * @type {Command[]}
     * @memberof BladeContainerBase
     */
    commands: Command[];
    /**
     * FormGroup对象
     * 
     * @type {FormGroup}
     * @memberof BladeContainerBase
     */
    formGroup: FormGroup;
    /**
     * FormBuilder对象
     * 
     * @type {FormBuilder}
     * @memberof BladeContainerBase
     */
    fromBuider: FormBuilder;
    /**
     * 表单错误对象
     * 
     * 
     * @memberof BladeContainerBase
     */
    formErrors: any;
    /**
     * 验证信息
     * 
     * 
     * @memberof BladeContainerBase
     */
    validationMessages: any;
    /**
    * 设置当前实体对象
    * 
    * 
    * @memberof BladeContainerBase
    */
    set currentEntity(data: T) {
        this.currentBlade.currentEntity = data;
    }
    /**
     * 获取当前实体对象
     * 
     * @type {*}
     * @memberof BladeContainerBase
     */
    get currentEntity(): T {
        return this.currentBlade.currentEntity;
    }
    /**
     * 获取父实体对象
     * 
     * @readonly
     * @type {*}
     * @memberof BladeContainerBase
     */
    get parentEntity(): any {
        return this.currentBlade.parentEntity;
    }
    /**
     * 获取弹出层服务对象
     * 
     * @readonly
     * @type {BladeService}
     * @memberof BladeContainerBase
     */
    get bladeService(): BladeService {
        return this.currentBlade.bladeService;
    }
    /**
    * 获取工具条服务对象
    * 
    * @readonly
    * @type {BladeService}
    * @memberof BladeContainerBase
    */
    get toolbarService(): ToolbarService {
        return this.currentBlade.toolbarService;
    }
    /**
     * 获取弹出层数据对象
     * 
     * @readonly
     * @type {BladeData}
     * @memberof BladeContainerBase
     */
    get bladeData(): BladeData {
        return this.currentBlade.bladeData;
    }
    /**
     * 获取弹出层的父对象
     * 
     * @readonly
     * @type {BladeService}
     * @memberof BladeContainerBase
     */
    get parentBlade(): Blade {
        return this.currentBlade.parentBlade;
    }
    /**
    * 获取弹出层的子对象数组
    * 
    * @readonly
    * @type {BladeService}
    * @memberof BladeContainerBase
    */
    get childrenBlades(): Blade[] {
        return this.currentBlade.childrenBlades;
    }
    /**
     * 获取对话框服务对象
     * 
     * @readonly
     * @type {DialogService}
     * @memberof BladeContainerBase
     */
    get dialogService(): DialogService {
        return this.currentBlade.dialogService;
    }
    /**
     * 获取标示创建或者编辑对象
     * 
     * @readonly
     * @type {boolean}
     * @memberof BladeContainerBase
     */
    get isNew(): boolean {
        return this.currentBlade.isNew;
    }
    /**
     * Creates an instance of BladeContainerBase.
     * @param {FormBuilder} _fromBuider 表单创建工厂
     * 
     * @memberof BladeContainerBase
     */
    constructor(private _fromBuider?: FormBuilder) {
        this.fromBuider = this._fromBuider;
    }
    /**
     * 
     * 
     * 
     * @memberof BladeContainerBase
     */
    ngOnInit(): void {
        setTimeout(() => this.bladeData.isLoading = false, 0);
        //如果没有FromBuider对象将不会去创建表单
        if (this.fromBuider != null) {
            this.setFormError();
            this.setValidationMessages();
            this.createForm();
            this.subscribeChanges();
        }
        this.registerCommand();
        this.initData();

    }
    /**
     * 初始化数据
     * 
     * @returns {(any | Observable<any> | Promise<any>)} 
     * 
     * @memberof BladeContainerBase
     */
    initData(): any | Observable<any> | Promise<any> {
        this.formPatchValue(this.currentEntity);
    }
    /**
     * 设置表单值
     * 
     * @param {*} data 
     * 
     * @memberof BladeContainerBase
     */
    formPatchValue(data: any) {
        if (this.formGroup != null) {
            console.log(this.currentEntity)
            this.formGroup.patchValue(this.currentEntity);
        }
    }
    /**
     * 创建表单
     * 
     * 
     * @memberof BladeContainerBase
     */
    createForm(): void {

    }
    /**
     * 订阅表单值变化
     * 
     * 
     * @memberof BladeContainerBase
     */
    subscribeChanges(): void {
        if (this.formGroup != null) {
            this.formGroup.valueChanges
                .subscribe(data => this.onValueChanged(data));
            this.formGroup.statusChanges
                .subscribe(data => this.onStatusChanged(data));
            this.formGroup.patchValue(this.currentEntity);
        }
    }


    /**
     * 表单值变化事件
     * 
     * @param {any} [data] 
     * 
     * @memberof BladeContainerBase
     */
    onValueChanged(data?: any): void {
        if (data != null) {
            this.formGroupChanged(this.formGroup);
        }
    }
    formGroupChanged(form: FormGroup) {
        if (form != null) {
            let controls = form.controls;
            if (controls != null) {
                let controlNames = Object.getOwnPropertyNames(controls);
                controlNames.forEach(controlName => {
                    if (controls[controlName] instanceof FormGroup) {
                        this.formGroupChanged(controls[controlName] as FormGroup);
                    }
                    else {
                        this.formErrors[controlName] = '';
                        let messages = this.validationMessages[controlName];
                        if (!controls[controlName].valid) {
                            for (const key in controls[controlName].errors) {
                                this.formErrors[controlName] = messages[key];
                            }
                        }

                    }
                })
            }
        }
    }

    /**
     * 表单状态变化事件
     * 
     * @param {any} [data] 
     * 
     * @memberof BladeContainerBase
     */
    onStatusChanged(data?: any): void {
        if (this.formGroup.status.toLowerCase() == "invalid") {
            this.onValueChanged(data);
        }
    }
    /**
     * 注册命令
     * 
     * 
     * @memberof BladeContainerBase
     */
    registerCommand(): void {
        if (this.commands != null) {
            for (let i = 0; i < this.commands.length; i++) {
                this.currentBlade.toolbarService.register(this.commands[i]);
            }
        }
    }
    /**
     * 刷新
     * 
     * @param {*} anyData 
     * 
     * @memberof BladeContainerBase
     */
    refresh(anyData: any): void {
        this.currentEntity = anyData;
        this.currentBlade.bladeData.isLoading = true;
        this.initData();
    }
    /**
     * 是否存在变更
     * 
     * @returns {boolean} 
     * 
     * @memberof BladeContainerBase
     */
    hasChange(): boolean {
        if (this.formGroup != null) {
            let enity = this.formGroup.value;
            let names: string[] = Object.getOwnPropertyNames(enity);         
            for (let i: number = 0; i < names.length; i++) {
                let name = names[i];                    
                if (this.currentEntity.hasOwnProperty(name)) {                    
                    let value = Object.getOwnPropertyDescriptor(this.currentEntity, name).value;             
                    if (value != enity[name]) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * 是否存在验证错误
     * 
     * @returns {boolean} 
     * 
     * @memberof BladeContainerBase
     */
    hasError(): boolean {
        if (this.formGroup != null) {
            return !this.formGroup.valid;
        }
        return false;
    }
    /**
     * 保存变更
     * 
     * 
     * @memberof BladeContainerBase
     */
    saveChange(): Promise<boolean> {
        return Promise.resolve(true);
    }
    /**
     * 创建对象
     * 
     * 
     * @memberof BladeContainerBase
     */
    create(): Promise<boolean> {
        return Promise.resolve(true);
    }
    /**
     * 是否可以卸载组件
     * 
     * @returns {(boolean | Promise<boolean> | Observable<boolean>)} 
     * 
     * @memberof BladeContainerBase
     */
    canDeactivate(): boolean | Promise<boolean> | Observable<boolean> {
        if (this.fromBuider != null && this.formGroup != null) {
            if (!this.formGroup.dirty) {
                return true;
            }
            else {
                return !this.hasChange() && !this.hasError();
            }
        }
        return true;
    }

    /**
    * 根据命令名称返回命令对象
    * 
    * @param {string} commandName 
    * @returns {Command} 
    * 
    * @memberof BladeContainerBase
    */
    getCommand(commandName: string): Command {
        return this.commands.find(o => o.name == commandName)
    }
    /**
     * 设置表单错误对象
     * 
     * 
     * @memberof BladeContainerBase
     */
    setFormError(): void { }
    /**
    * 设置表单验证信息
    * 
    * 
    * @memberof BladeContainerBase
    */
    setValidationMessages(): void { }
    /**
     * 关闭之前调用
     * 
     * @returns {(boolean | Observable<boolean> | Promise<boolean>)} 
     * 
     * @memberof BladeContainerBase
     */
    beforeClosing(): Promise<boolean> {
        let thisBlade = this;
        return new Promise((resolve, reject) => {
            try {
                if (!thisBlade.canDeactivate()) {
                    if (thisBlade.hasError()) {
                        thisBlade.dialogService.showConfirmationDialog("警告", `${thisBlade.bladeData.title} 检测到错误，是否需要修改？`)
                            .subscribe(dialogResult => {
                                switch (dialogResult) {
                                    case DialogResult.Ok:
                                        resolve(false);
                                        break;
                                    case DialogResult.no:
                                        resolve(true);
                                        break;
                                    case DialogResult.cancel:
                                        resolve(false);
                                        break;
                                }
                            });
                    }
                    else if (thisBlade.hasChange()) {
                        thisBlade.dialogService.showConfirmationDialog("警告", `${thisBlade.bladeData.title} 检测到变更，是否需要${thisBlade.isNew ? "创建" : "保存"}？`)
                            .subscribe(dialogResult => {
                                switch (dialogResult) {
                                    case DialogResult.Ok:
                                        if (!this.isNew) {
                                            thisBlade.saveChange().then(res => {
                                                if (res) {
                                                    resolve(true);
                                                }
                                                else {
                                                    resolve(false);
                                                }
                                            });
                                        }
                                        else {
                                            thisBlade.create().then(res => {
                                                if (res) {
                                                    resolve(true);
                                                }
                                                else {
                                                    resolve(false);
                                                }
                                            });
                                        }
                                        break;
                                    case DialogResult.no:
                                        resolve(true);
                                        break;
                                    case DialogResult.cancel:
                                        resolve(false);
                                        break;
                                }
                            });
                    }
                }
                else {
                    resolve(true);
                }
            }
            catch (error) {
                reject(error);
            }
        });
    }


    /**
     * 关闭之后调用
     * 
     * @returns {(void | Observable<void> | Promise<void>)} 
     * 
     * @memberof BladeContainerBase
     */
    closed(): Promise<any> {
        return null;
    }

}


// WEBPACK FOOTER //
// ./src/app/shared/blade/blade-container-base.ts